﻿using AutoMapper;
using DTcms.Core.Common.Emum;
using DTcms.Core.Common.Extensions;
using DTcms.Core.Common.Helper;
using DTcms.Core.DBFactory.Database;
using DTcms.Core.IServices;
using DTcms.Core.Model.Models;
using DTcms.Core.Model.ViewModels;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace DTcms.Core.Services
{
    /// <summary>
    /// 文章接口实现
    /// </summary>
    public class ArticleService : BaseService, IArticleService
    {
        private readonly IMapper _mapper;
        private readonly IUserService _userService;

        public ArticleService(
            IDbContextFactory contentFactory,
            IUserService userService,
            IMapper mapper) : base(contentFactory)
        {
            _userService = userService;
            _mapper = mapper;
        }

        /// <summary>
        /// 查询一条记录
        /// </summary>
        public async Task<Articles> QueryAsync(Expression<Func<Articles, bool>> funcWhere, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            var result = await _context.Set<Articles>()
                .Include(x => x.ArticleAlbums)
                .Include(x => x.ArticleAttachs)
                .Include(x => x.ArticleFields)
                .Include(x => x.ArticleCategoryRelations).ThenInclude(x => x.ArticleCategory)
                .Include(x => x.ArticleLabelRelations).ThenInclude(x => x.ArticleLabel)
                .Include(x => x.SiteChannel)
                .FirstOrDefaultAsync(funcWhere);
            return result;
        }

        /// <summary>
        /// 修改一条记录
        /// </summary>
        public async Task<bool> UpdateAsync(long id, ArticlesEditDto modelDto, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            //查找记录
            var model = await _context.Set<Articles>()
                .Include(x => x.ArticleAlbums)
                .Include(x => x.ArticleAttachs)
                .Include(x => x.ArticleFields)
                .Include(x => x.ArticleCategoryRelations).ThenInclude(x => x.ArticleCategory)
                .Include(x => x.ArticleLabelRelations).ThenInclude(x => x.ArticleLabel)
                .FirstOrDefaultAsync(x => x.Id == id);

            if (model == null)
            {
                throw new ResponseException($"数据{id}不存在或已删除", ErrorCode.NotFound);
            }
            //检查频道是否存在
            var channelModel = await _context.Set<SiteChannel>().FirstOrDefaultAsync(x => x.Id == modelDto.ChannelId);
            if (channelModel == null)
            {
                throw new ResponseException($"频道{modelDto.ChannelId}不存在或已删除", ErrorCode.NotFound);
            }
            //检查站点是否存在
            if (await _context.Set<Sites>().FirstOrDefaultAsync(x => x.Id == channelModel.SiteId) == null)
            {
                throw new ResponseException($"站点{model.SiteId}不存在或已删除", ErrorCode.NotFound);
            }
            //AutoMapper将DTO映射到源数据
            _mapper.Map(modelDto, model);
            model.SiteId = channelModel.SiteId;
            model.UpdateBy = await _userService.GetUserNameAsync();
            model.UpdateTime = DateTime.Now;

            //提交保存
            return await this.SaveAsync();

        }

        /// <summary>
        /// 更新数据(局部更新)
        /// </summary>
        public async Task<bool> UpdateAsync(Articles model, Expression<Func<Articles, int>> funcProperty, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            var entry = _context.Entry<Articles>(model);
            //设置修改状态
            entry.State = EntityState.Unchanged;
            entry.Property(funcProperty).IsModified = true;
            //提交保存
            int res = await _context.SaveChangesAsync();
            return res > 0;
        }

        /// <summary>
        /// 更新浏览量(局部更新)
        /// </summary>
        public async Task<int> UpdateClickAsync(long articleId, int clickCount, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            Articles model = new Articles();
            model.Id = articleId;
            model.Click = clickCount;

            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            var entry = _context.Entry<Articles>(model);
            //设置修改状态
            entry.State = EntityState.Unchanged;
            entry.Property(p => p.Click).IsModified = true;
            //提交保存
            int res = await _context.SaveChangesAsync();
            if (res > 0)
            {
                return model.Click;
            }
            else
            {
                return 0;
            }
        }

        /// <summary>
        /// 查询文章分页数据
        /// </summary>
        /// <param name="pageSize">页大小</param>
        /// <param name="pageIndex">当前页</param>
        /// <param name="funcWhere">查询条件</param>
        /// <param name="orderBy">排序</param>
        /// <param name="writeAndRead"></param>
        /// <returns></returns>
        public async Task<PaginationList<Articles>> QueryPageAsync(int pageSize, int pageIndex,
            Expression<Func<Articles, bool>> funcWhere,
            string orderBy,
            WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            IQueryable<Articles> result = _context.Set<Articles>()//条件筛选
                .Include(x => x.ArticleCategoryRelations).ThenInclude(x => x.ArticleCategory)
                .Include(x => x.ArticleLabelRelations).ThenInclude(x => x.ArticleLabel)
                .Include(x => x.ArticleAlbums)
                .Include(x => x.ArticleAttachs)
                .Where(funcWhere);
            result = LinqExtensions.OrderByBatch<Articles>(result, orderBy);//调用Linq扩展类排序

            return await PaginationList<Articles>.CreateAsync(pageIndex, pageSize, result);
        }

        /// <summary>
        /// 获取记录总数量
        /// </summary>
        public async Task<int> QueryCountAsync(Expression<Func<Articles, bool>> funcWhere, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            return await _context.Set<Articles>().Where(funcWhere).CountAsync();
        }

        /// <summary>
        /// 查询文章前几条数据
        /// </summary>
        public async Task<IEnumerable<Articles>> QueryListAsync(int top, Expression<Func<Articles, bool>> funcWhere, string orderBy, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            IQueryable<Articles> result = _context.Set<Articles>()//条件筛选
                .Include(x => x.ArticleCategoryRelations).ThenInclude(x => x.ArticleCategory)
                .Include(x => x.ArticleLabelRelations).ThenInclude(x => x.ArticleLabel)
                .Include(x => x.ArticleAlbums)
                .Include(x => x.ArticleAttachs)
                .Where(funcWhere);
            result = LinqExtensions.OrderByBatch<Articles>(result, orderBy);//调用Linq扩展类排序

            if (top > 0) result = result.Take(top);
            return await result.ToListAsync();
        }
    }
}
